package testcase.command;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.NoSuchElementException;

import junit.framework.TestCase;

import org.junit.Test;

import satir.card.Choice;
import satir.card.Question;
import satir.command.AskQuestionCmd;
import satir.player.Player;

public class AskQuestionCmd_execute_1 extends TestCase{
	
	class PlayerStub extends Player{
		private int selfEsteem;
		public PlayerStub(){
			selfEsteem=5;
		}
		@Override
		public void increaseSelfEsteem(int increaseValue){
			selfEsteem+=increaseValue;
		}
		public int getValue (){
			return selfEsteem;
		}
	};
	public static class AskQuestionCmdStub extends AskQuestionCmd {
		public AskQuestionCmdStub(Question question, Player player) {
			super(question, player);
		}
		@Override
		protected void askQuestion(final ArrayList<Choice> choices){
			System.out.println("Please indicate your selection");
		}
		
		public void doExecute(){
			this.execute();
		}
		
	};

	private AskQuestionCmdStub askQuestionCmdStub;
	private PlayerStub playerStub;
	
/**
 * Sets up the test fixture. Called before every test case method.
 */
public void setUp() {

	// give choice
	ArrayList<Choice> choices;
	choices = new ArrayList<Choice>();
	choices.add(new Choice(
			"Blame him/her and prohibit use the phone more than 5 mins.",
			1, new Hashtable<String, Integer>()));
	choices.add(new Choice("Talk with son/daughter and find the reason.",
			1, new Hashtable<String, Integer>()));
	choices.add(new Choice(
			"Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.",
			-1, new Hashtable<String, Integer>()));
	choices.add(new Choice("Ignore him/her.", -1,
			new Hashtable<String, Integer>()));

	// give a question
	String question1 = "Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?";
	playerStub = new PlayerStub();
	Question question = new Question(question1, choices);

	// create questions array
	ArrayList<Question> questions = new ArrayList<Question>();
	questions.add(question);

	 askQuestionCmdStub = new AskQuestionCmdStub(question, playerStub);
}
/**
 * Tears down the test fixture. Called after every test case method.
 */
public void tearDown() {
}
	
	/*
	 * Step: 1
	 * Objective: Test whether it will print out the question of event Q1 and those choices and then award(increase) correct Self-Esteem value for Q1 C1 to player or not
	 */
	@Test 
	public void testAnswerQuestion1WithChoice1(){
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "1";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			askQuestionCmdStub.doExecute();
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\r\n" +
				"1. Blame him/her and prohibit use the phone more than 5 mins.\r\n" +
				"2. Talk with son/daughter and find the reason.\r\n" +
				"3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\r\n" +
				"4. Ignore him/her.\r\n" +
				"Your Answer?\r\n" +
				"1 Awarded!!\r\n");

		assertEquals(actualResult,expectedResult);
		int SEresult = playerStub.getValue();
		assertEquals(6,SEresult);
	}
	
	/*
	 * Step: 2
	 * Objective: Test whether it will print out the question of event Q1 and those choices and then award(decease) correct Self-Esteem value for Q1C4 to player or not
	 */
	@Test 
	public void testAnswerQuestion1WithChoice4(){
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "4";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			askQuestionCmdStub.doExecute();
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\r\n" +
				"1. Blame him/her and prohibit use the phone more than 5 mins.\r\n" +
				"2. Talk with son/daughter and find the reason.\r\n" +
				"3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\r\n" +
				"4. Ignore him/her.\r\n" +
				"Your Answer?\r\n" +
				"-1 Awarded!!\r\n");

		assertEquals(actualResult,expectedResult);
		int SEresult = playerStub.getValue();
		assertEquals(4,SEresult);
	}
	
	/*
	 * Step: 3
	 * Objective: Test whether it will print out the question of event Q1 and those choices and then print error message for answering a out of range answer or not
	 */
	@Test 
	public void testAnswerQuestion1With5(){
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "5 1";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			askQuestionCmdStub.doExecute();
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\r\n" +
				"1. Blame him/her and prohibit use the phone more than 5 mins.\r\n" +
				"2. Talk with son/daughter and find the reason.\r\n" +
				"3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\r\n" +
				"4. Ignore him/her.\r\n" +
				"Your Answer?\r\n" +
				"Out of range!\r\n" +
				"Please indicate your selection\r\n" +
				"1 Awarded!!\r\n");

		assertEquals(actualResult,expectedResult);
		int SEresult = playerStub.getValue();
		assertEquals(6,SEresult);

	}
	/*
	 * Step: 4
	 * Objective: Test whether it will print out the question of event Q1 and those choices and then print error message for answering a letter answer or not
	 */
	@Test 
	public void testAnswerQuestion1Witha(){
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "a 1";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			askQuestionCmdStub.doExecute();
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\r\n" +
				"1. Blame him/her and prohibit use the phone more than 5 mins.\r\n" +
				"2. Talk with son/daughter and find the reason.\r\n" +
				"3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\r\n" +
				"4. Ignore him/her.\r\n" +
				"Your Answer?\r\n" +
				"It is not a number.\r\n" +
				"Please indicate your selection\r\n" +
				"1 Awarded!!\r\n");

		assertEquals(actualResult,expectedResult);
		int SEresult = playerStub.getValue();
		assertEquals(6,SEresult);
	}
	/*
	 * Step: 5
	 * Objective: Test whether it will print out the question of event Q1 and those choices and then print error message for answering a Symbol answer or not
	 */
	@Test 
	public void testAnswerQuestion1WithSymbol(){
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output here
		String input = "@ 1";
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			askQuestionCmdStub.doExecute();
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here
		
		String actualResult = systemOut.toString();
		String expectedResult = ("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\r\n" +
				"1. Blame him/her and prohibit use the phone more than 5 mins.\r\n" +
				"2. Talk with son/daughter and find the reason.\r\n" +
				"3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\r\n" +
				"4. Ignore him/her.\r\n" +
				"Your Answer?\r\n" +
				"It is not a number.\r\n" +
				"Please indicate your selection\r\n" +
				"1 Awarded!!\r\n");

		assertEquals(actualResult,expectedResult);
		int SEresult = playerStub.getValue();
		assertEquals(6,SEresult);
	}
}